home *** CD-ROM | disk | FTP | other *** search
/ United Public Domain Gold 2 / United Public Domain Gold 2.iso / utilities / pu745.dms / pu745.adf / GLOBE099.LHA / Ami-Globe / iff / jiff.c next >
C/C++ Source or Header  |  1994-11-05  |  9KB  |  372 lines

  1.  
  2. /**********************************************************************
  3. *
  4. *           jiff.c   Jim Kent's iff - ilbm  reader
  5. *
  6. * This is the (sortof) short (sortof) simple no-frills IFF reader
  7. * to get something out of DPaint, Images, or the Animator.  It
  8. * works well with the Aztec C compiler.  It should work with Lattice
  9. * but you never know until you try it.  I haven't.
  10. *
  11. * I've included a simple main program.  This is just to make it
  12. * stand alone.  Since amiga screen initializations are massive, all
  13. * it does as is is read it into a BitMap, and then free up the BitMap.
  14. * Should crash it if it's gonna crash though.
  15. *
  16. * The main interface to this is through the routine read_iff(filename).
  17. * This returns a ILBM_info structure-pointer on success, and NULL on
  18. * failure.  It cleans up after itself on failure.
  19. *
  20. * I hope you will find this useful and easy to use.  Please forgive
  21. * my funky indentation style?  Well at least I'm consistent!
  22. *
  23. * To demonstrate what a nice guy I am even though I'm far from wild
  24. * about the IFF standard I'm placing this in the public domain.  When
  25. * you remove the DEBUG and PARANOID definitions the code is only
  26. * 1536 bytes long.
  27. *
  28. *       -Jim Kent  April 22, 1986
  29. ************************************************************************/
  30.  
  31. #include <stdio.h>
  32. #include <string.h>
  33. #include <exec/types.h>
  34. #include <exec/memory.h>
  35. #include <graphics/gfx.h>
  36. #include <libraries/dos.h>
  37. #include "jiff.h"
  38.  
  39.  
  40. #define TAILLE_BUFFER   1024
  41. char    buffer[TAILLE_BUFFER];
  42. int nb=0;
  43.  
  44. /*this is an all too common state of software development.  Get rid
  45.   of this define as soon as it runs*/
  46. /*
  47. #define DEBUG
  48. */
  49. /*this is the normal state of software development.  Seriously undefine
  50.   this to make it shut up about errors and reduce code size half way
  51.   through beta testing... */
  52. /*
  53. #define PARANOID
  54. */
  55. static struct ILBM_info *read_ilbm(), *read_body();
  56.  
  57. /* OK this code is almost re-entrant.  Pass this guy from above to
  58.    make it really re-entrant.  (Why do you need a reentrant ILBM
  59.    reader though??  Maybe for Dale ... ) */
  60. static struct ILBM_info root_info;  /*static so get initialized to zero*/
  61.  
  62.  
  63. #ifdef PARANOID
  64. /* a little paranoid routine that say's where we got before EOF */
  65. static void
  66. iff_truncated(where)
  67. int where;
  68. {
  69. free_planes(&root_info.bitmap);
  70. }
  71. #endif
  72.  
  73.  
  74. int my_Read(hdlr,p,taille)
  75. BPTR    hdlr;
  76. char    *p;
  77. int taille;
  78. {
  79.     int i;
  80.  
  81.     for(i=0;i<taille;i++){
  82.         if(nb==0){
  83.             Read(hdlr,&buffer,TAILLE_BUFFER);
  84.             nb=TAILLE_BUFFER;
  85.         }
  86.         p[i]=buffer[TAILLE_BUFFER-nb];
  87.         nb--;
  88.     }
  89.     return(taille);
  90. }
  91.  
  92. int my_Seek(hdlr,taille,type)
  93. BPTR    hdlr;
  94. int taille,type;
  95. {
  96.     int i;
  97.  
  98.     if(taille<=nb){
  99.         nb=nb-taille;
  100.     }else{
  101.         taille=taille-nb;
  102.         Seek(hdlr,taille,type);
  103.     }
  104. }
  105.  
  106. BPTR    my_Open(name,mode)
  107. char    *name;
  108. long    int mode;
  109. {
  110.     nb=0;
  111.     return(Open(name,mode));
  112. }
  113.  
  114. struct ILBM_info *read_iff( char *name,short just_colors)
  115. {
  116. struct ILBM_info *info = &root_info;
  117. BPTR hdlr;
  118. struct form_chunk chunk;
  119.  
  120.     info->camg=0;
  121. if ((hdlr = my_Open(name, MODE_OLDFILE) ) == 0)
  122.     {
  123.     return(NULL);
  124.     }
  125.  
  126. if ( my_Read(hdlr,&chunk, sizeof(struct form_chunk)) !=sizeof(struct form_chunk))
  127.     {
  128. #ifdef PARANOID
  129.     iff_truncated(0);
  130. #endif
  131.     Close(hdlr);
  132.     return(NULL);
  133.     }
  134.  
  135. if (chunk.fc_type.b4_type != FORM)
  136.     {
  137.     Close(hdlr);
  138.     return(NULL);
  139.     }
  140.  
  141. if (chunk.fc_subtype.b4_type != ILBM)
  142.     {
  143. #ifdef PARANOID
  144.     printf("FORM not an ILBM - %s\n", name);
  145. #endif
  146.     Close(hdlr);
  147.     return(NULL);
  148.     }
  149.  
  150. #ifdef DEBUG
  151. printf("FORM %ld ILBM\n", chunk.fc_length);
  152. #endif
  153.  
  154. info = read_ilbm(hdlr, info, chunk.fc_length - sizeof(chunk), just_colors);
  155. Close(hdlr);
  156. return(info);
  157. }
  158.  
  159. static
  160. struct ILBM_info *
  161. read_ilbm(hdlr, info, length, just_colors)
  162. BPTR *hdlr;
  163. struct ILBM_info *info;
  164. long length;
  165. short just_colors;
  166. {
  167. struct iff_chunk chunk;
  168. int i;
  169. long read_in = 0;
  170. int got_header = FALSE;  /*to make sure gots the header first*/
  171. int got_cmap = FALSE;  /*make sure get cmap before "BODY" */
  172.  
  173. /*make sure the Planes are all NULL so can free up memory easily
  174.   on error abort */
  175. for (i=0; i<8; i++)
  176.     info->bitmap.Planes[i] = NULL;
  177.  
  178. while (read_in < length)
  179.     {
  180.     if (my_Read(hdlr,&chunk, sizeof(chunk)) !=sizeof(chunk))
  181.         {
  182. #ifdef PARANOID
  183.         iff_truncated(1);
  184. #endif
  185.         return(NULL);
  186.         }
  187.     switch (chunk.iff_type.b4_type)
  188.         {
  189.         case BMHD:
  190. #ifdef DEBUG
  191.             printf("\tBMHD %ld\n", chunk.iff_length);
  192. #endif
  193.             if (my_Read(hdlr,&info->header, sizeof(info->header)) != sizeof(info->header))
  194.                 {
  195. #ifdef PARANOID
  196.                 iff_truncated(2);
  197. #endif
  198.                 return(NULL);
  199.                 }
  200.             got_header = TRUE;
  201.             break;
  202.         case CAMG:
  203.             my_Read(hdlr,&info->camg, 4);
  204.             break;
  205.         case CMAP:
  206.             if (!got_header){
  207.                     return(NULL);
  208.             }
  209.             info->cmap=(UBYTE *)malloc(chunk.iff_length/3);
  210.             if(info->cmap){
  211.  
  212.                 if(my_Read(hdlr,info->cmap, (int)chunk.iff_length) !=(int)chunk.iff_length){
  213.                     return(NULL);
  214.                 }
  215.                 info->Nb_Col=chunk.iff_length/3;
  216.             }else{
  217.                 info->Nb_Col=0;         
  218.                 bit_bucket(hdlr, chunk.iff_length);
  219.             }
  220.             got_cmap = TRUE;
  221.             if (just_colors)
  222.                 return(info);
  223.             break;
  224.         case BODY:
  225.             if (!got_cmap)
  226.                 {
  227.                 return(NULL);
  228.                 }
  229.             return( read_body(hdlr, info, chunk.iff_length) );
  230.  
  231.         default:    /*squawk about unknown types if PARANOID */
  232.         case GRAB:  /*ignore documented but unwanted types*/
  233. /*        case DEST:  */
  234.         case SPRT:
  235.         case CRNG:
  236.         case CCRT:
  237.             bit_bucket(hdlr, chunk.iff_length);
  238.             break;
  239.         }
  240.     read_in += chunk.iff_length + sizeof(chunk);
  241.     }
  242. return(NULL); 
  243. }
  244.  
  245.  
  246.  
  247. static struct ILBM_info *read_body(
  248.     BPTR    hdlr,
  249.     register struct ILBM_info *info,
  250.     long length
  251. )
  252. {
  253. struct ILBM_header *header;
  254. struct BitMap *bm;
  255. int i, j;
  256. int rlength;
  257. int plane_offset;
  258.  
  259.  
  260. /* ok a little more error checking */
  261. if (info->header.compression != 0 && info->header.compression != 1)
  262.     {
  263.     return(NULL);
  264.     }
  265.  
  266. /*set up the bitmap part that doesn't involve memory allocation first -
  267.   hey this part does get done, and let's be optimistic...*/
  268. info->bitmap.BytesPerRow = line_bytes(info->header.w);
  269. info->bitmap.Rows = info->header.h;
  270. info->bitmap.Depth = info->header.nPlanes;
  271. info->bitmap.Flags = info->bitmap.pad = 0;
  272.  
  273. rlength = info->bitmap.Rows * info->bitmap.BytesPerRow;
  274.  
  275. for (i=0; i<info->header.nPlanes; i++)
  276.     {
  277.     if ((info->bitmap.Planes[i] = ralloc(rlength)) == NULL)
  278.         {
  279.         free_planes( &info->bitmap );
  280.         return(NULL);
  281.         }
  282.     }
  283. plane_offset = 0;
  284. for (i=0; i<info->bitmap.Rows; i++)
  285.     {
  286.     /* this test should be in the inner loop for shortest code,
  287.        in the outer loop for greatest speed, so sue me I compromised */
  288.     if (info->header.compression == 0)
  289.         {
  290.         for (j = 0; j < info->bitmap.Depth; j++)
  291.             {
  292.             if ( my_Read(hdlr,info->bitmap.Planes[j] + plane_offset,
  293.                 info->bitmap.BytesPerRow) !=info->bitmap.BytesPerRow)
  294.                 {
  295. #ifdef PARANOID
  296.                 iff_truncated(6);
  297. #endif
  298.                 free_planes( &info->bitmap);
  299.                 return(NULL);
  300.                 }
  301.             }
  302.         }
  303.     else
  304.         {
  305.         register char *dest;
  306.         char    value;
  307.         register int so_far, count;  /*how much have unpacked so far*/
  308.  
  309.         for (j = 0; j < info->bitmap.Depth; j++)
  310.             {
  311.             so_far = info->bitmap.BytesPerRow;
  312.             dest = (char *)info->bitmap.Planes[j] + plane_offset;
  313.             while (so_far > 0)
  314.                 {
  315.                 my_Read(hdlr,&value,1);
  316.                 if (value == 128)
  317.                     {
  318.                     }
  319.                 else if (value > 0)
  320.                     {
  321.                     count = (int)value + 1;
  322.                     so_far -= count;
  323.                     if ( my_Read(hdlr,dest, count) !=count)
  324.                         {
  325. #ifdef PARANOID
  326.                         iff_truncated(7);
  327. #endif
  328.                         free_planes( &info->bitmap);
  329.                         return(NULL);
  330.                         }
  331.                     dest += count;
  332.                     }
  333.                 else 
  334.                     {
  335.                     count = (int)-value + 1;
  336.                     so_far -= count;
  337.                     my_Read(hdlr,&value,1);
  338.                     while (--count >= 0)  /*this is fastest loop in C */
  339.                         *dest++ = value;
  340.                     }
  341.                 }
  342.             if (so_far != 0)
  343.                 {
  344. #ifdef PARANOID
  345.                 printf("compression quite screwed up, aborting %d\n", so_far);
  346. #endif
  347.                 free_planes( &info->bitmap);
  348.                 return(NULL);
  349.                 }
  350.             }
  351.         }
  352.     plane_offset += info->bitmap.BytesPerRow;
  353.     }
  354. return(info);
  355. }
  356.  
  357.  
  358. void free_planes(register struct BitMap *bmap)
  359. {
  360. PLANEPTR plane;
  361. long length;
  362. short i;
  363.  
  364. length = bmap->BytesPerRow * bmap->Rows;
  365.  
  366. for (i=0; i<8; i++)
  367.     if ( (plane = bmap->Planes[i]) != NULL)
  368.         rfree(plane, length);
  369. }
  370.  
  371.  
  372.